#include <iostream>
#include <pthread.h>
#include <vector>
#include <unistd.h>
#include <cstdio>
#include <cstring>

using namespace std;

pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;         //全局锁并初始化

#define NUM 4

//共享数据————可能导致数据不一致
//买一张票的过程：1.将内存里的tickets读入寄存器 2.CPU内部操作 3.将计算结果写回内存
int tickets=3000;               
 

class threadData
{
public:
    threadData(int num)
    {
        threadname="thread-"+to_string(num);
    }
public:
    string threadname;
};

void *buyTicket(void *args)
{
    threadData *td=static_cast<threadData*>(args);
    const char *name=td->threadname.c_str();

    while(1)
    {   
        pthread_mutex_lock(&lock);
        if(tickets>0)
        {
            usleep(1000);
            printf("%s buy a ticket ticket: %d\n",name,tickets);
            tickets--;
            pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
        usleep(10);            //模拟抢到票的后续操作，用usleep代替后续操作，以至于不会让该线程一直占用锁
    }
    printf("%s ... quit\n",name);
    return nullptr;
}

int main()
{
    pthread_mutex_t lock;
    pthread_mutex_init(&lock,nullptr);

    //两容器存放线程id和线程数据
    vector<pthread_t> tids;
    vector<threadData*> thread_datas;
    for(int i=0;i<NUM;i++)
    {
        pthread_t tid;

        //创建线程数据对象，放入容器
        threadData *td=new threadData(i);
        thread_datas.push_back(td);

        pthread_create(&tid,nullptr,buyTicket,thread_datas[i]);
        tids.push_back(tid);
    }

    for(auto thread:tids)
    {
        pthread_join(thread,nullptr);
    }
 
    for(auto td:thread_datas)
    {
        delete td;
    }
    pthread_mutex_destroy(&lock);
    return 0;
}